package com.ruoyi.syrw.aspectj;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.base.domain.BaHehUseLog;
import com.ruoyi.base.mapper.BaHehUseLogMapper;
import com.ruoyi.base.service.IBaHehUseLogService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;

import com.ruoyi.syrw.annotation.DealHeh;
import com.ruoyi.report_tg.domain.bo.ExcelGeneralBo;

import com.ruoyi.syrw.domain.RefReportExcel;
import com.ruoyi.syrw.domain.vo.RefReportExcelVo;
import com.ruoyi.syrw.mapper.BiExcelTypeMapper;
import com.ruoyi.syrw.mapper.RefReportExcelMapper;
import com.ruoyi.syrw.service.IBiExcelTypeService;
import com.ruoyi.syrw.service.IRefReportExcelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 记录盒号的使用， 源自需求： “每个盒号一天只能用一次”
 *
 * @author zyb
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
@Order(80)
public class DealHehAspect {

    private final IBaHehUseLogService baHehUseLogService;
    private final BaHehUseLogMapper hehUseLogMapper;
    private final IRefReportExcelService refReportExcelService;
    private final RefReportExcelMapper refReportExcelMapper;
    private final BiExcelTypeMapper biExcelTypeMapper;
    private final IBiExcelTypeService biExcelTypeService;


    /**
     * 从承载比一二处 引用内容 覆盖 承载三的内容
     *
     * @param joinPoint 切点
     */
    @Around(value = "@annotation(dealHeh)")
    public Object dealHeh(ProceedingJoinPoint joinPoint, DealHeh dealHeh) throws Throwable {
        if (ObjUtil.isEmpty(joinPoint.getArgs()) || ObjUtil.isEmpty(joinPoint.getArgs()[0])) {
            throw new ServiceException("注解使用有误，或者被注解的方法不规范，请联系管理员解决。详细：" + joinPoint.getSourceLocation().toString());
        }
        ExcelGeneralBo bo = (ExcelGeneralBo) joinPoint.getArgs()[0];
        Long excelId = bo.getExcelId();
        Assert.notNull(excelId, "excelId不能为空");
        String shiyjcrq = bo.getShiyjcrq();
        Assert.notNull(shiyjcrq, "试验检测日期不能为空");
        DateTime useDate = DateUtil.parse(shiyjcrq, Constants.EXCEL_DATE_FORMAL);
        List<Long> hehIdList = bo.getHehIdList();
        // 表格名称
        RefReportExcelVo refReportExcelVo = refReportExcelMapper.selectVoOne(new LambdaQueryWrapper<RefReportExcel>()
            .eq(RefReportExcel::getExcelId, excelId));
        refReportExcelVo.setVo(biExcelTypeMapper.selectById(refReportExcelVo.getExcelTypeId()));

        if (ObjUtil.isNull(hehIdList)) {
            throw new ServiceException(refReportExcelVo.getExcelTypeName() + "盒号ID列表【hehIdList】, 不能为Null。请检查传参和接口接收参数是否继承ExcelGeneralBo");
        }
        // 检查hehId是否有重复
        List<Long> collect = hehIdList.stream().distinct().collect(Collectors.toList());
        if (collect.size() < hehIdList.size()) {
            throw new ServiceException("检测到在" + refReportExcelVo.getExcelTypeName() + "中, 存在重复使用的盒号，请检查后重试");
        }


        if (CollUtil.isNotEmpty(hehIdList)) {
            // 1. 检查如果有不可用的则 抛异常
            boolean exists = hehUseLogMapper.exists(new LambdaQueryWrapper<BaHehUseLog>()
                .eq(BaHehUseLog::getUseDate, useDate) // 当天的
                .ne(BaHehUseLog::getExcelId, excelId) // 其他excel使用的
                .in(BaHehUseLog::getHehId, hehIdList));// 在此次的使用hehId中
            if (exists) {
                throw new ServiceException("在 " + refReportExcelVo.getExcelTypeName() + " 中存在不可选用的盒号，请检查后重试");
            }
        }
        // 2. 删掉excelId下 当天的 所有记录
        hehUseLogMapper.delete(new LambdaQueryWrapper<BaHehUseLog>()
            .eq(BaHehUseLog::getUseDate, useDate)
            .eq(BaHehUseLog::getExcelId, excelId));
        // 3. 新增excelId下 当天的 记录
        if (CollUtil.isNotEmpty(hehIdList)) {
            hehIdList.forEach(v -> {
                BaHehUseLog baHehUseLog = new BaHehUseLog();
                baHehUseLog.setHehId(v);
                baHehUseLog.setExcelId(excelId);
                baHehUseLog.setUseDate(useDate);
                hehUseLogMapper.insert(baHehUseLog);
            });
        }
        return joinPoint.proceed();
    }

}
